\documentclass [12pt, a4paper]{report}

\usepackage[spanish]{babel} 
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{ucs}
\usepackage{url}
\usepackage[utf8x]{inputenc}
\usepackage{afterpage}
\usepackage{appendix}

\begin{document}

%CARATULA-------------------------------------------------------------------------------------------------------------------
\title{Sistemas Operativos\vskip 1cm \textsc{Informe Técnico Proyecto Final}}
\author{Martinelli, Fernán G., Riberi Franco G.}
\date{\today} 

\maketitle
\newpage
\pagenumbering{roman} 
\pagenumbering{arabic}
%INDICE GENERAL--------------------------------------------------------------------------------------
\newpage
\tableofcontents 

%INDICE DE FIGURAS-------------------------------------------------------------------------------------
\newpage
\listoffigures

\newpage
\chapter*{Introducción}
En un comienzo, las primeras computadoras carecían de sistema operativo (S.O), cada programa debería programarse lo suyo. Más tarde, aparecieron los primeros transistores y sistemas de procesamiento por lotes donde se ejecutaba un proceso a la vez. A mediados de los 60, aparecen los primeros S.O para sistemas compartidos, permitiendo la multiprogramación y el multiprocesamiento.
Luego, surgieron los circuitos integrados, permitiendo mejorar la utilización de CPU y el paralelismo entre CPU y entrada-salida. Por último, surgieron los S.O modernos, con tiempo compartido, S.O de red, S.O distribuidos entre otros. Aparecen los programas interactivos, shells gráficas, entre otras características. 

De esta forma se introduce el concepto de \emph{Sistema Operativo}. Básicamente se trata de un administrador de recursos que actúa como interface entre los usuarios/aplicaciones y el hardware de un sistema informático.

El presente informe corresponde al proyecto final de la asignatura Sistemas Operativos (Cód 1965). El mismo consiste en la implementación de diferentes llamadas al sistema sobre el \emph{File System} de \emph{xv6}\footnote{Re-implementación de Dennis Ritchie’s y Ken Thompson del Unix Version 6 (v6). Implementado en el lenguaje de programación ANSI C para un procesador x86}.

Esta breve documentación está formada por 5 capítulos los cuales reflejan el camino transitado. En el \textit{capítulo 1} se presenta el enunciado del trabajo a realizar propuesto por la asignatura. En el \textit{capítulo 2} se detalla brevemente un marco teórico respecto al sistema de archivos de xv6. En el \textit{capítulo 3} se enumeran algunas aclaraciones a tener en cuenta. En el \textit{capítulo 4} se exhibe paso a paso la solución implementada. Por último, en el \textit{capítulo 5} se meciona como se verificó el funcionamiento de lo implementado. \\
A continuación se presenta dicho trabajo. \\

\chapter{Especificaciones del Proyecto}
\par A continuación se exhibe el enunciado del proyecto.

\par Extender \emph{xv6} para que soporte las llamadas al sistema sobre archivos \textsf{int fseek(int fd, int pos)}, \textsf{int flock(int fd)} y \textsf{int funlock(int fd)}.

\par La primera llamada al sistema permite posicionar el cursor lógico en un archivo.

\par Las dos últimas llamadas al sistema implementarán un mecanismo de sincronización básico bloqueando o desbloqueando un archivo para permitir a los procesos el acceso exclusivo.

\par Además se deberá extender el sistema de archivos para soportar permisos sobre archivos. Los permisos sobre un archivo serán \textsf{rwx}. Esto incluye que se deberán controlar los permisos durante la apertura (\textsf{open}) y ejecución de programas (\textsf{exec}).

\par Como programas de usuario deberán extender el comando \textsf{ls} para que muestre los permisos asociados a los archivos (al estilo \textsf{UNIX}) y deberán implementar la llamada al sistema \textsf{int chmod(char * filename, int mode)}, donde \textsf{mode} es el valor de los permisos en octal (1:ejecución, 2:escritura, 4:lectura).

\par Ayuda: ver los módulos \textsf{file.c, fs.c}.

\chapter{Marco Teórico \emph{xv6}}
\section{Compilación de xv6}
Para la compilación del SO xv6 se emplea \textsf{make}\cite{make}. En el código fuente se encuentra un archivo \textsf{Makefile} que contiene instrucciones de compilación para make. El resultado de la compilación es el siguiente:
\begin{enumerate}
\item \textbf{bootblock:} código del bootsector (\textsf{bootasm.S} y \textsf{bootmain.c}).
\item \textbf{kernel:} código del kernel (\textsf{entry.S}, \textsf{exec.c}, \textsf{file.c}, ...).
\item \textbf{Programas de usuario:}  (\textsf{sh.c}, \textsf{ls.s}, ...).
\item \textbf{fs.img:} imagen del sistema de archivos conteniendo los programas de usuario, 
\item \textbf{xv6.img:} imagen de disco con la concatenacion de \textsf{bootblock}, \textsf{kernel} y \textsf{fs.img}. Luego esta imagen puede levantarse desde \emph{qemu}\cite{qemu} o cargarse desde un \emph{bootloader}.
\end{enumerate}

\section{Inicio de xv6}
La BIOS carga el sector de booteo y realiza un salto a esa dirección. Luego se deshabilitan las interrupciones, se setean los registros de la CPU, pasa a modo 32 bits e invoca a \textsf{bootmain()}. Se carga el kernel asumiendo que comienza en el sector 1. Luego salta al punto de entrada en el kernel (entry.S).
\textsf{entry()} define el mapa de memoria, setea los registros \textsf{cr3} y \textsf{cr0} habilitando el paginado, setea el stack inicial de kernel y salta al \textsf{main()}. Se inicializa un nuevo mapa de memoria, la lista de bloques libres y varios subsistemas e inicia el primer proceso de usuario \textsf{init}.
En la figura \ref{inicio} se intenta graficar dicho proceso con más detalles.

\begin{figure}[h!]
	\centering
		\includegraphics[scale=0.5]{image/inicio.png}
	\caption{Inicio de xv6}
	\label{inicio} 
\end{figure} 	
 
\section{File System}
\par La implementación está organizada básicamente en 6 capas o \emph{layers}, tal como se observa en la figura \ref{layers}. La \emph{capa más baja}, lee y escribe los bloques en el disco a través de una memoria caché, que sincroniza el acceso a bloques de disco, asegurándose de que sólo una copia de un bloque está en la memoria y que sólo un proceso del kernel a la vez utilize dicha copia. La \emph{segunda capa} permite asegurar que los bloques se actualizan atómicamente en una transacción (es decir, todos ellos se actualizan o ninguno). La \emph{tercera capa} proporciona archivos sin nombre, cada uno representado con un \textsf{inode} y una secuencia de bloques que contienen datos de archivos. La \emph{cuarta capa} implementa directorios como un tipo especial de \textsf{inode} cuyo contenido es una secuencia de entradas de directorios. La \emph{quinta capa} proporciona nombres jerárquicos como path (e.g /usr/rtm/xv6/fs.c), utilizando búsqueda recursiva. Por último, la \emph{capa final} abstrae muchos recursos de UNIX mediante la interfaz del sistema de archivos, simplificando el desarrollo de aplicaciones. 

Para una información más específica de cada layer ver \cite{xv6}.

\begin{figure}[h!]
	\centering
		\includegraphics[scale=0.5]{image/fs.png}
	\caption{Implementación del \emph{File System.}}
	\label{layers} 
\end{figure} 	

Para almacenar los \textsf{inode} y bloques de contenido en el disco, xv6 divide el mismo en varias secciones, tal como se observa en la figura \ref{disco}. 

\begin{figure}[h!]
	\centering
		\includegraphics[scale=0.5]{image/disco.png}
	\caption{Estructura del sistema de archivos xv6.} %definida en fs.h
	\label{disco} 
\end{figure} 	

Básicamente el sistema de archivos no utiliza el bloque 0 (que posee el sector de arranque). El bloque 1, conocido como \emph{superbloque}, contiene toda la metadata a cerca del sistema de archivos. A partir del bloque 2 comienzan los \textsf{inodes}, con múltiples inode por bloque. Después de esos se encuentran los bloques de mapa de bits que vienen seguidos de qué bloques de datos están en uso. La mayor parte de los bloques restantes son de datos, que poseen el contenido del archivo y del directorio. Los bloques en el final del disco se emplean para mantener el registro de transacciones. 

Las principales estructuras definidas en el sistema de archivos se exhiben a continuación: 
\vskip 1.2cm
\noindent $[---inode---]	\hspace{5cm}				[---file---]$ \\
$[\hspace{3.34cm}] \hspace{5cm}				[\hspace{3.05cm}]$ \\
$[\hspace{3.34cm}]	\hspace{5cm}				[\hspace{3.05cm}]$ \\
$[\hspace{1.5cm}...\hspace{1.5cm}]\hspace{5cm}			[\hspace{1.35cm}...\hspace{1.35cm}]$ \\
$[\hspace{3.34cm}]<----------\hspace{.24cm}[\hspace{1.35cm}ip\hspace{1.35cm}]$ \\
$[\hspace{1.3cm}mod\hspace{1.3cm}]                                    $ \\ 

\subsection{File}
Un descriptor de archivo es un entero pequeño que representa un objeto que un proceso puede leer o escribir gestionado a nivel kernel. 
Un proceso puede obtener un descriptor de archivo al abrir un archivo, directorio o dispositivo, o mediante la creación de un pipe, o duplicar un descriptor existente. Internamente, el núcleo xv6 utiliza el descriptor de archivo como un índice en una tabla por proceso, de modo que cada proceso tiene un espacio privado de descriptores de archivos a partir de cero.
Por convención, un proceso lee de descriptor de archivo 0 (entrada estándar), escribe la salida al descriptor de fichero 1 (salida estándar), y escribe mensajes de error al descriptor de fichero 2 (error estándar). Como veremos, el shell explota el convenio para implementar la redirección de E/S y pipes. El shell se asegura de que siempre tiene tres descriptores de archivos abiertos, que son los descriptores de archivo por defecto para la consola.
Las llamadas al sistema leer y escribir leen y escriben bytes en archivos abiertos con el nombre de descriptores de fichero. 
La llamada read (fd, buf, n) lee como mucho n bytes desde el archivo descriptor fd, los copia en buf y devuelve el número de bytes leídos. 
Cada descriptor de fichero tiene asociado un desplazamiento de la misma. Read lee datos desde el archivo en la posición actual y avanza el número de bytes leídos; Por ejemplo en una lectura posterior leerá los n bytes siguientes.

La representación interna del un objeto File es la siguiente:
\vskip .5cm
\noindent [----------------------------FILE----------------------------] \\
 type: enum { FD\_NONE, FD\_PIPE, FD\_INODE }	 \\
 ref : int											\\  
 readable : char 							\\
 writable : char 							 \\
 pipe : pipe* 								 \\
 off: uint									\\
 ip :inode*								

\subsection{inode}
El término \textsf{inode} puede tener dos significados. Por un lado, puede referirse a la estructura de datos en disco que contiene diferentes metadatos (figura \ref{enDisco}), tales como el tipo del archivo, su tamaño, el número de referencias, la lista de bloques que poseen el contenido del  archivo, etcétera, y por el otro, a un \textsf{inode} en memoria, que contiene una copia del \textsc{inode} en disco, entre otros datos.

\begin{figure}[h!]
	\centering
		\includegraphics[scale=0.35]{image/archivoDisco.png}
	\caption{Representación de un archivo en disco.}
	\label{enDisco} 
\end{figure} 	


Todos los inodes en disco se situan en un área contigua del mismo y poseen el mismo tamaño. Cada uno esta definido por una estructura \textsf{dinode} (\textsf{fs.h}). El campo \emph{type} distingue entre archivo, directorio y fichero especiales. Si \emph{type} es cero indica que el inodo en disco esta libre.

Por otro lado, el kernel mantiene un conjunto de \textsf{inode} en memoria, representados por una estructura \textsf{inode} (\textsf{file.h}).


\chapter{Aclaraciones}
\begin{itemize}
\item Las carpetas son \textsf{inodes} por lo tanto también tienen permisos.
\item Un proceso puede usar la llamada al sistema \textsf{chmod}.
\item Como no hay usuarios, los permisos pertenecen a un archivo (todos los procesos tienen los mismos permisos de archivo).
\item Permisos por defecto al crear un archivo: MODE\_RWX.
\item El archivo \textsf{README} de xv6 fue eliminado ya que no era creado por el sistema sino que por el Makefile. Como posible solución se propone implementar un programa usuario \textsf{readme.c}, que básicamente cree un archivo README y lo escriba con el contenido adecuado. Este programa usuario deberia ser invocado desde \textsf{sh.c}. De esta manera el archivo README tendría su correspondiente inode. Una aproximación de este programa sería:

\begin{verbatim}
int
main(int argc, char *argv[]){
  int fd;
  char* buf = "contenido adecuado";
  fd = open("README", O_CREATE | O_RDWR);
  if(fd < 0){
      printf(1, "Error al crear el archivo. \n");
      return -1;
  }
  write(fd,&buf,1);
  close(fd);
}
\end{verbatim}
\end{itemize}

\chapter{Resolución}
\par Para permitir que \textsf{xv6} soporte llamadas al sistema sobre archivos fue necesario su implementación. A continuación se detalla de manera general los diversos pasos y acciones realizadas.

\begin{enumerate}
\item Agregamos en la estructura \textsf{inode} el campo \textsf{mod}, el cual será empleado para el manejo de los permisos. (\emph{file.h}).

\begin{verbatim}
    struct inode {
        uint dev;    // Device number
        uint inum;   // Inode number
        int ref;     // Reference count
        int flags;   // I_BUSY, I_VALID
        ...
        short unsigned int mod;     //empleado para los permisos  
    };
\end{verbatim}

\item Se agrego el nuevo campo \emph{mod} en el archivo \emph{stat.h}. Básicamente, stat es un objeto que se emplea para copiar la información importante de un inode en ejecución.

\begin{verbatim}
    struct stat {
        short type;  // Type of file
        ...
        short unsigned int mod;
    };
\end{verbatim}

\item Se modificó la funcion \textsf{stati} definida en \emph{fs.c} agregando el campo ya mencionado. Esta función copia la información desde un inode.

\begin{verbatim}
        void
        stati(struct inode *ip, struct stat *st)
        {
          ...
          st->mod = ip->mod;
        }
\end{verbatim}

\item En \emph{fs.h} se definieron los siguientes permisos:
\begin{verbatim}
   #define MODE_X   0x1
   #define MODE_W   0x2
   #define MODE_WX  0x3
   #define MODE_R   0x4
   #define MODE_RX  0x5
   #define MODE_RW  0x6
   #define MODE_RWX 0x7
\end{verbatim}

\item Se modificó el programa de usuario \textsf{ls} (\emph{ls.c}) para que muetre los permisos de cada archivo, de esta forma añadiendo el flag \textsf{-l} se exhibiran los archivos con sus respectivos permisos. Además se definió una función (\textsf{mode\_to\_string}) para mostrar los permisos en formato legible (no como un entero).

\begin{verbatim}
    char* 
    mode_to_string(int mode)
    {
        if(mode==MODE_X)
            return "x";
        if(mode==MODE_RW)
            return "r-w";
        if(mode==MODE_WX)
            return "w-x";
        if(mode==MODE_W)
            return "w";
        if(mode==MODE_RWX)
            return "r-w-x";
        if(mode==MODE_RX)
            return "r-x";
        if(mode==MODE_RX)
            return "r-x";
        else
            return "!!!!";
    } 
\end{verbatim}

\item (\textsf{fs.c}) En la creación, seteamos todos los privilegios para un \textsf{inode}, es decir, \textsf{MODE\_RWX}.

\begin{verbatim}
    struct inode *ip;
    ...
    ip->mod = MODE_RWX;
    ...
\end{verbatim}

\item Se añadieron las siguiente interrupciones en \emph{syscall.h}.
\begin{verbatim}
        #define SYS_chmod         28
        #define SYS_fseek         29
        #define SYS_flock         30
        #define SYS_funlock       31
\end{verbatim}
 
\item Se añadieron las interrupciones mencionadas anteriormente en el vector de manejo de interrupciones (\emph{syscall.c}) y además se definieron como externos\footnote{La implementación se encuentra en la archivo \emph{sysfile.c}} los perfiles de las funciones que implementarán el comportamiento del sistema en cada caso.
\begin{verbatim}
    ...
    extern int sys_chmod(void);
    extern int sys_fseek(void);
    extern int sys_flock(void);
    extern int sys_funlock(void);

    static int (*syscalls[])(void) = {   
    ...
    [SYS_chmod] 	sys_chmod,  --> funciones definidas en sysfile.c
    [SYS_fseek]		sys_fseek,  --> [...] refiere a las interrupciones
    [SYS_flock]		sys_flock,
    [SYS_funlock]	sys_funlock,
    ...
    }
\end{verbatim}

\item Se definieron (\emph{sysfile.c}) las distintas funciones encargadas del tratamiento de cada interrupción. Estas funciones serán llamadas desde el programa usuario. En cada una se realiza un chequeo de los parámetros de entrada y se invocan. A continuación se exhibe la implementación de las funciones. 

\begin{verbatim}
int
sys_chmod(void)
{
    char * filename;
    int mode;
    if(argstr(0, &mode) < 0)
        return -3;
    if(argint(1, &filename) < 0)
        return -3;
    if(mode < 1 || mode > 7)
        return -2;
    return chmod(mode, filename);
}
\end{verbatim}

\begin{verbatim}
int
sys_fseek(void)
{
    int fd,pos;
    if(argint(0, &fd) < 0)
        return -1;
    if(argint(1, &pos) < 0)
        return -1;
    return fseek(proc->ofile[fd],pos);
}
\end{verbatim}

\begin{verbatim}
int
sys_flock(void)
{
    int fd;
    if(argint(0, &fd) < 0)
        return -1;
    return flock(fd);
}
\end{verbatim}

\begin{verbatim}
int
sys_funlock(void)
{
    int fd;
    if(argint(0, &fd) < 0)
        return -1;
    return funlock(fd);
}
\end{verbatim}

\item \textsf{file.c} implementación de las funciones. 

\begin{verbatim}
int
chmod(int mode, char* filename)
{
    struct inode *ip;
    if((ip = namei(filename)) == 0)
        return -1;
    ilock(ip);
    begin_trans();
      ip->mod = mode;
      iupdate(ip);
    commit_trans();
    iunlock(ip);
    return 0;
}
\end{verbatim}

\begin{verbatim}
int
fseek(struct file *f, int pos)
{	
    if (pos<0 || pos > f->ip->size){
        release(&ftable.lock);
        return -1;
    }
    f->off = pos;
    begin_trans();
      ilock(f->ip);
      f->off = pos;
      iunlock(f->ip);
    commit_trans();
    return 0;
}
\end{verbatim}

\begin{verbatim}
int
flock(int fd)
{
    if (fd<0 || fd>NFILE -1){
         return -1;
    }
    if(ftable.locks[fd]==-1){
        ftable.locks[fd]=semget(-1,1);
        if(ftable.locks[fd]==-1){
            return -1;
        }
    }
    semdown(ftable.locks[fd]);
    return 0;
}
\end{verbatim}

\begin{verbatim}
int
funlock(int fd)
{
    if (fd<0 || fd>NFILE -1){
         return -1;
    }
    if(ftable.locks[fd]==-1){
        ftable.locks[fd]=semget(-1,1);
        if(ftable.locks[fd]==-1){
            return -1;
        }
    }
    semup(ftable.locks[fd]);
    return 0;
}
\end{verbatim}

\item \textsf{user.h} se definieron los perfiles de las llamadas al sistema desde el modo usuario.
\begin{verbatim}
    int chmod(int, char*);
    int fseek(int, int);
    int flock(int);
    int funlock(int);
\end{verbatim}

\item \textsf{usys.S} se agregaron las llamadas al sistema explícitamente.
\begin{verbatim}
    SYSCALL(chmod)
    SYSCALL(fseek)
    SYSCALL(flock)
    SYSCALL(funlock)
\end{verbatim}
A partir de este momento, desde un programa usuario se pueden hacer llamadas a estas funciones.

\item Se definió un programa usuario \textsf{chmod} en el directorio \textsf{/user}. Se añadió este archivo en el Makefile para su compilación correspondiente.

\begin{verbatim}
int
main(int argc, char *argv[])
{
  int ret;
  if(argc != 3){
    printf(1, "Cannot execute chmod. \n");
    exit();
  }else{
    ret = chmod(atoi(argv[1]), argv[2]);
    if (ret == -1){
        printf(1, "Cannot execute chmod. Incorrect file. \n");
        exit();
    }else{
      if (ret == -2){
          printf(1, "Cannot execute chmod. Incorrect mode. \n");
          exit();
      }else
        exit();
    }                 
  }
}
\end{verbatim}

\item Se controlaron los permisos en \textsf{open} (\textsf{sysfile.c}),\textsf{exec} (\textsf{exec.c}), \textsf{read} y \textsf{write} (\textsf{file.c}) para apertura, ejecución, lectura y escritura respectivamente.

\begin{verbatim}
int
sys_open(void)
{
    ...
    if(omode == O_RDONLY){
        if(ip->mod != MODE_R && ip->mod != MODE_RW && 
           ip->mod != MODE_RX && ip->mod != MODE_RWX)
            return -1;
    }
    if(omode == O_WRONLY){
        if(ip->mod != MODE_W && ip->mod != MODE_RW && 
           ip->mod != MODE_WX && ip->mod != MODE_RWX)
            return -1;
    }
    if(omode == O_RDWR){
        if(ip->mod != MODE_RW && ip->mod != MODE_RWX)
            return -1;
    }
    ...
}
\end{verbatim}

\begin{verbatim}
int
exec(char *path, char **argv)
{
    ...
    if(ip->mod != MODE_X && ip->mod != MODE_RX &&
       ip->mod != MODE_WX && ip->mod != MODE_RWX)
        return -1;
    ...
}
\end{verbatim}

\begin{verbatim}
int
fileread(struct file *f, char *addr, int n)
{
    ...
    if(f->ip->mod != MODE_R && f->ip->mod != MODE_RW && 
       f->ip->mod != MODE_RX && f->ip->mod != MODE_RWX)
        return -2;
    ...
}
\end{verbatim}

\begin{verbatim}
int
filewrite(struct file *f, char *addr, int n)
{
   ...
   if(f->ip->mod != MODE_W && f->ip->mod != MODE_RW && 
      f->ip->mod != MODE_WX && f->ip->mod != MODE_RWX)
       return -2;
   ... 
}
\end{verbatim}
\end{enumerate}

\chapter{Test de lo desarrollado}
Para testear las llamadas al sistema desarrolladas, se creó un programa usuario \textsf{lockTest.c}. Básicamente la idea es crear varios procesos que lean el valor almacenado en un archivo, le sumen uno, y luego lo escriban. Usando los bloqueos \textsf{flock} y \textsf{funlock} el valor final del archivo debe ser exactamente igual a la cantidad de procesos (inicialmente el valor del archivo es 0). A continuación se puede observar el código correspondiente:

\begin{verbatim}
int
main(int argc, char *argv[])
{
    ...
    fd = open("file.txt", O_CREATE | O_RDWR);
    if(fd < 0){
        printf(1, "Error al crear el archivo. \n");
        return -1;
    }
    write(fd,&init,1);
    close(fd);
    for(i = 0; i < LIMIT; ++i){
        pid=fork();  
        if (pid == 0){            
            fd = open("file.txt", O_RDWR);
            flock(fd);
            read(fd, &buf, sizeof(buf));
            buf++;
            fseek(fd,0);
            write(fd ,&buf, sizeof(buf));
            funlock(fd);
            close(fd);            
      }else{
          //padre  
          wait();
          exit();
      }  
    }
    ...
}
\end{verbatim}

Para testear la llamada al sistema \textsf{chmod} se sugiere lo siguiente:
\begin{enumerate}
\item Escoger un archivo a modificar sus permisos.
\item \textsf{chmod $<$mode$>$ archivoSeleccionado}
\item Ejecutamos \textsf{ls -l}
\item Los permisos del archivo seleccionado cambiaron.
\end{enumerate}

Un ejemplo claro, para observar el funcionamiento es ejecutar \textsf{chmod 4 ls}. Se le otorgan permisos de lectura al programa de usuario \textsf{ls}. Si ejecutamos \textsf{ls}, no va a funcionar, dado que no tiene permisos de ejecución. 

\newpage
\begin{thebibliography}{99}

\bibitem{xv6} {\em{``xv6 a simple, Unix-like teaching operating system''. }}
		\textsc{Russ Cox, Frans Kaashoek and Robert Morris.} Draft as of september 7, 2011.

\bibitem{make} {\em{``Make: \textcolor{blue}{http://www.gnu.org/software/make/}''. }}

\bibitem{make} {\em{``Qemu: \textcolor{blue}{http://wiki.qemu.org}''. }}


\end{thebibliography}

\end{document}
